import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Like, In } from 'typeorm';
import * as XLSX from 'xlsx';
import { Product } from './entities/product.entity';
import { Category } from './entities/category.entity';
import { ProductQueryDto } from './dto/product-query.dto';
import { CreateCategoryDto } from './dto/create-category.dto';
import { UpdateCategoryDto } from './dto/update-category.dto';
import { CreateProductDto } from './dto/create-product.dto';
import { validate } from 'class-validator';
import { ImportCategoryDto } from './dto/import-category.dto';
import { ImportProductDto } from './dto/import-product.dto';

/**
 * 商品服务类
 * 处理商品和分类的查询、创建、更新和删除等业务逻辑
 */
@Injectable()
export class ProductService {
  /**
   * 根据ID获取商品详情
   * @param id - 商品ID
   * @returns 商品详情对象
   * @throws NotFoundException - 当商品不存在时抛出
   */
  async findOneProduct(id: string): Promise<Product> {
    const product = await this.productRepository.findOne({
      where: { id: Number(id) },
      relations: ['category'],
    });

    if (!product) {
      throw new NotFoundException('商品不存在');
    }

    return product;
  }
  constructor(
    @InjectRepository(Product) private productRepository: Repository<Product>,
    @InjectRepository(Category) private categoryRepository: Repository<Category>,
  ) {}

  /**
   * 获取商品列表（分页查询）
   * @param query - 包含分页参数、搜索关键词和分类筛选的查询对象
   * @returns 包含商品列表和分页元数据的对象
   */
  async findAllProducts(query: ProductQueryDto) {
    const { page, limit, search, categoryId } = query;
    const skip = (page - 1) * limit;
    const where: any = {};

    // 添加搜索条件
    if (search) {
      where.name = Like(`%${search}%`);
    }

    // 添加分类筛选条件
    if (categoryId) {
      where.categoryId = categoryId;
    }

    // 执行分页查询
    const [products, total] = await this.productRepository.findAndCount({
      where,
      skip,
      take: limit,
      relations: ['category'],
      order: { createdAt: 'DESC' },
    });

    return {
      list: products,
      meta: {
        total,
        page,
        limit,
        totalPages: Math.ceil(total / limit),
      },
    };
  }

  /**
   * 获取所有商品分类
   * @returns 活跃分类列表
   */
  /**
   * 获取所有商品分类
   * @returns 活跃分类列表（按id从小到大排序）
   */
  async findAllCategories() {
    return this.categoryRepository.find({
      where: { isActive: true },
      order: { id: 'ASC' },//确保商品分类按id从小到大返回
    });
  }

  /**
   * 根据ID获取分类详情
   * @param id - 分类ID
   * @returns 分类详情对象
   */
  async findCategoryById(id: string) {
    return this.categoryRepository.findOneBy({ id: Number(id) });
  }

  /**
   * 创建新分类
   * @param category - 包含分类信息的对象
   * @returns 创建后的分类对象
   */
  async createCategory(category: Partial<Category>) {
    const newCategory = this.categoryRepository.create(category);
    return this.categoryRepository.save(newCategory);
  }

  /**
   * 更新分类信息
   * @param id - 分类ID
   * @param updates - 包含更新信息的对象
   * @returns 更新后的分类对象
   */
  async updateCategory(id: string, updates: Partial<Category>) {
    await this.categoryRepository.update(id, updates);
    return this.findCategoryById(id);
  }

  /**
   * 软删除分类（标记为非活跃）
   * @param id - 分类ID
   * @returns 操作结果
   */
  async removeCategory(id: string) {
    await this.categoryRepository.update(id, { isActive: false });
    return { success: true };
  }

  /**
   * 创建新商品
   * @param createProductDto - 包含商品信息的DTO对象
   * @returns 创建成功的商品实体
   * @throws NotFoundException - 当分类不存在时抛出
   */
  async createProduct(createProductDto: CreateProductDto): Promise<Product> {
    // 验证分类是否存在
    const categoryExists = await this.categoryRepository.existsBy({
      id: createProductDto.categoryId
    });

    if (!categoryExists) {
      throw new NotFoundException('分类不存在');
    }

    // 创建商品实体并保存
    const product = this.productRepository.create(createProductDto);
    return this.productRepository.save(product);
  }

  /**
   * 从Excel文件批量导入分类
   * @param fileBuffer - Excel文件缓冲区
   * @returns 导入结果，包含成功和失败数量
   */
  async importCategories(fileBuffer: Buffer): Promise<{ success: number; failed: number; successes: Array<{ row: number; data: any }>; errors: Array<{ row: number; error: string }> }> {
    const workbook = XLSX.read(fileBuffer, { type: 'buffer' });
    const worksheet = workbook.Sheets[workbook.SheetNames[0]];
    const jsonData: ImportCategoryDto[] = XLSX.utils.sheet_to_json(worksheet);

    const result = { 
      success: 0, 
      failed: 0, 
      successes: [] as Array<{ row: number; data: any }>,
      errors: [] as Array<{ row: number; error: string }> 
    };

    for (const [index, item] of jsonData.entries()) {
      try {
        const categoryDto = new ImportCategoryDto();
        categoryDto.name = item.name;
        categoryDto.description = item.description;
        const validationErrors = await validate(categoryDto);
        if (validationErrors.length > 0) {
          const errorMessages = validationErrors.flatMap(err => err.constraints ? Object.values(err.constraints) : []);
          throw new BadRequestException(errorMessages.join('; '));
        }

        const existingCategory = await this.categoryRepository.findOneBy({ name: item.name });
        if (existingCategory) {
          throw new BadRequestException(`第${index + 2}行: 分类名称 "${item.name}" 已存在`);
        }

        // 创建新分类
        const newCategory = this.categoryRepository.create(item);
        await this.categoryRepository.save(newCategory);
        result.successes.push({ row: index + 2, data: newCategory });
        result.success++;
      } catch (error) {
        result.failed++;
        result.errors.push({
          row: index + 2,
          error: error.message,
        });
      }
    }

    return result;
  }

  async importProducts(fileBuffer: Buffer): Promise<{ success: number; failed: number; successes: Array<{ row: number; data: any }>; errors: Array<{ row: number; error: string }> }> {
    const workbook = XLSX.read(fileBuffer, { type: 'buffer' });
    const worksheet = workbook.Sheets[workbook.SheetNames[0]];
    const jsonData: ImportProductDto[] = XLSX.utils.sheet_to_json(worksheet);

    const result = { 
      success: 0, 
      failed: 0, 
      successes: [] as Array<{ row: number; data: any }>,
      errors: [] as Array<{ row: number; error: string }> 
    };

    for (const [index, item] of jsonData.entries()) {
      try {
        // 验证DTO数据
        const productDto = new ImportProductDto();
        Object.assign(productDto, item);
        const validationErrors = await validate(productDto);
        if (validationErrors.length > 0) {
          const errorMessages = validationErrors.flatMap(err => err.constraints ? Object.values(err.constraints) : []);
          throw new BadRequestException(`第${index + 2}行: ${errorMessages.join('; ')}`);
        }

        // 检查分类是否存在
        const categoryExists = await this.categoryRepository.existsBy({ id: item.categoryId });
        if (!categoryExists) {
          throw new BadRequestException(`第${index + 2}行: 分类ID ${item.categoryId} 不存在`);
        }

        // 创建新产品
        const newProduct = this.productRepository.create(productDto);
        await this.productRepository.save(newProduct);
        result.successes.push({ row: index + 2, data: newProduct });
        result.success++;
      } catch (error) {
        result.failed++;
        result.errors.push({
          row: index + 2,
          error: error.message || '未知错误'
        });
      }
    }

    return result;
  }
}
